#ifndef READER_H
#define READER_H

/*
 * The API for getting card data from the card reader
 * 
 * @author Jonathan Walsh (jdw74@drexel.edu)
 */

#define VERBOSE /*Turn this off to disable printing in system functions*/
//#define EXTRA_VERBOSE /*Turn this off to disable a lot of debugging*/
#define READ_BUFFER_SIZE 300  /*300 bytes should be enough right?*/

#define SERIAL_DEVICE_TTY "/dev/ttyS0"

/*mag card sentinal values (SS = Start Sentinal, ES = End Sentinal)*/
#define CARD_TRACK1_SS '%'
#define CARD_TRACK2_SS ';'
#define CARD_TRACK3_SS ';'
#define CARD_TRACK3_SS_AAMVA '%'
#define CARD_TRACK3_SS_CADMV '!'
#define CARD_ES '?'
#define CARD_DLE LF

/* some ascii control chars... wtf this should be in some system header... */
#define NUL 0x00
#define SOH 0x01
#define STX 0x02
#define ETX 0x03
#define LF  0x10

/*Credit Card field separators*/
#define CARD_CC_SEPARATOR '^'
#define CARD_CC_ES '?'


/*********** DEVICE C&C FUNCTIONS *************/
/*
 * Connect to the device and get the port
 * 
 * @return file descriptor for the device, or -1 on error
 */
int get_device_port();

/*
 * Close the device down
 *
 * @param fd - File descriptor for the device
 * @return 0 on success, 1 on error
 */
int close_device_port( int fd );


/**************** READ FUNCTIONS ********************/
/*
 * Read in a single card
 * 
 * @param fd - the device port; must already be configured
 * @return length of the card data on success, 0 on error
 */
int read_card( int fd, char **card_return, int card_return_len );

/*
 * Continually read in data and print out what is read in.  Good for testing
 *  multiple cards!
 * 
 * @param fd - the device port; must already be configured
 * @return Only returns on error, value of -1
 */
int read_device_and_print( int fd );


/*********** HELPFUL OUTPUT FUNCTIONS ********************/
/*
 * Print the raw bytes for a card
 * 
 * @param card - The card data
 * @param len - Length of the card data
 * @return 0 on success, 1 on error
 */
int print_card_by_raw_bytes( char *card, int len );

/*
 * Print the raw bytes for a card split by track with sentinals
 * 
 * @param card - The card data
 * @param len - Length of the card data
 * @param track_nl - If 1 print a newline for the track end, if 0 dont
 * @return 0 on success, 1 on error
 */
int print_card_by_values( char *card, int len, int track_nl );


/*************** CREDIT CARD SPECIFIC FUNCTIONALITY ***********/
typedef struct credit_card_data_t {
  char format_code;  /*this should always be 'B'*/
  char account_num[20];
  char name[27];
  char exp[5];
  char service_code[4];
  char discretionary_data[250]; /*how long is this???*/
} credit_card_data;
/*
 * Parse the card data into the credit card standard as specified 
 * by ISO/IEC 7813.
 * 
 * Oddly enough, in this standard Track 1 has all the data. Since in
 *  ISO/IEC 7811 Track 2 has lower bpi, it contains a copy of *some* of
 *  track 1's data.  Track 3 is unused in the standard.  In my tests, the 
 *  reader always returns the no data value of 'N'.  But I digress...
 *
 * Also note that the reader does not return the LRC, must be stripped before 
 *   presentation layer.
 *
 * @param card - Raw card data
 * @param len - Raw card data length
 * @param data - Output parameter of card data
 * @return 0 on success, 1 on failure
 */
int parse_card_as_credit_card( char *card, int len, credit_card_data *data );
/*
 * Print out the credit card data
 * 
 * @param data The credit card data to print
 * @return 0
 */
int print_credit_card( credit_card_data *data );


#endif /*READER_H*/
